/*************************************************************************
	> File Name: netlink_test.c
	> Author: Thinking
	> Mail: program_code@sohu.com 
	> Created Time: Sun 20 Feb 2022 12:01:02 AM UTC
 ************************************************************************/

#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/netfilter_ipv4.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h> 

static unsigned int NET_HookLocalIn(
	void *priv, 
	struct sk_buff *skb, 
	const struct nf_hook_state *state)
{
	int retval = NF_ACCEPT;

	if (skb){	
		struct tcphdr *tcph;
		struct iphdr *iph;
		struct udphdr *udph;
		iph = ip_hdr(skb);  // 获取ip头  
		if( iph->protocol == IPPROTO_TCP )  
		{
			tcph = tcp_hdr(skb);
			
			if( htons(tcph->source) == 80 || 
				htons(tcph->source) == 443)  
			{
				printk("netfilter_tcp, %u -- %u\n", htons(tcph->source),htons(tcph->dest));
				retval = NF_DROP;
			}  
		}
		else if( iph->protocol == IPPROTO_UDP )  
		{
			udph = udp_hdr(skb);
			if( htons(udph->source) == 443)	 
			{
				printk("netfilter_udp, %u -- %u\n", htons(udph->source),htons(udph->dest));
				retval = NF_DROP;
			}  
		}
	}
	return retval;
}


static struct nf_hook_ops nfho = {
	.hook		= NET_HookLocalIn,			// 发往本地数据包  
	.pf			= PF_INET,					//protocol family, ipv4即这个
	.hooknum	= NF_INET_LOCAL_IN,			//hook所在的位置
	.priority	= NF_IP_PRI_FIRST,			//优先级
};

static int cn_netlink_init(void)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0)
    //nf_unregister_net_hooks(&init_net, app_filter_ops, ARRAY_SIZE(app_filter_ops));
#else
	//nf_unregister_hooks(app_filter_ops, ARRAY_SIZE(app_filter_ops));
#endif


	nf_register_net_hook(&init_net, &nfho);
	return 0;
}

static void cn_netlink_uninit(void)
{
	nf_unregister_net_hook(&init_net, &nfho);
}

module_init(cn_netlink_init);
module_exit(cn_netlink_uninit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
MODULE_DESCRIPTION("Connector's test module");
